using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace CKY.AgentPlatform.ModelConfigs
{
    /// <summary>
    /// 熔断器状态
    /// </summary>
    public enum CircuitState
    {
        /// <summary>
        /// 关闭状态 - 正常工作
        /// </summary>
        Closed,

        /// <summary>
        /// 开启状态 - 熔断中，拒绝请求
        /// </summary>
        Open,

        /// <summary>
        /// 半开启状态 - 尝试恢复
        /// </summary>
        HalfOpen
    }

    /// <summary>
    /// 熔断器配置
    /// </summary>
    public class CircuitBreakerConfig
    {
        /// <summary>
        /// 失败阈值（连续失败次数）
        /// </summary>
        public int FailureThreshold { get; set; } = 5;

        /// <summary>
        /// 熔断超时时间（毫秒）
        /// </summary>
        public int TimeoutMs { get; set; } = 30000;

        /// <summary>
        /// 半开启状态下的尝试次数
        /// </summary>
        public int HalfOpenAttempts { get; set; } = 3;

        /// <summary>
        /// 成功重置次数（连续成功次数后重置熔断器）
        /// </summary>
        public int SuccessThreshold { get; set; } = 2;

        /// <summary>
        /// 滑动窗口时间（毫秒）
        /// </summary>
        public int SlidingWindowMs { get; set; } = 60000;

        /// <summary>
        /// 异常过滤器（决定哪些异常应该触发熔断）
        /// </summary>
        public Func<Exception, bool> ExceptionFilter { get; set; } = ex => true;

        /// <summary>
        /// 熔断器名称
        /// </summary>
        public string Name { get; set; }
    }

    /// <summary>
    /// 熔断器统计信息
    /// </summary>
    public class CircuitBreakerStats
    {
        /// <summary>
        /// 总请求数
        /// </summary>
        public long TotalRequests { get; set; }

        /// <summary>
        /// 成功请求数
        /// </summary>
        public long SuccessRequests { get; set; }

        /// <summary>
        /// 失败请求数
        /// </summary>
        public long FailedRequests { get; set; }

        /// <summary>
        /// 当前状态
        /// </summary>
        public CircuitState State { get; set; }

        /// <summary>
        /// 最后状态变更时间
        /// </summary>
        public DateTime LastStateChange { get; set; }

        /// <summary>
        /// 连续失败次数
        /// </summary>
        public int ConsecutiveFailures { get; set; }

        /// <summary>
        /// 连续成功次数
        /// </summary>
        public int ConsecutiveSuccesses { get; set; }

        /// <summary>
        /// 半开启尝试次数
        /// </summary>
        public int HalfOpenAttemptCount { get; set; }

        /// <summary>
        /// 成功率
        /// </summary>
        public double SuccessRate => TotalRequests > 0 ? (double)SuccessRequests / TotalRequests : 0;

        /// <summary>
        /// 失败率
        /// </summary>
        public double FailureRate => TotalRequests > 0 ? (double)FailedRequests / TotalRequests : 0;
    }

    /// <summary>
    /// 熔断器事件参数
    /// </summary>
    public class CircuitBreakerEventArgs : EventArgs
    {
        /// <summary>
        /// 熔断器名称
        /// </summary>
        public string CircuitBreakerName { get; set; }

        /// <summary>
        /// 旧状态
        /// </summary>
        public CircuitState OldState { get; set; }

        /// <summary>
        /// 新状态
        /// </summary>
        public CircuitState NewState { get; set; }

        /// <summary>
        /// 变更原因
        /// </summary>
        public string Reason { get; set; }

        /// <summary>
        /// 变更时间
        /// </summary>
        public DateTime Timestamp { get; set; }

        /// <summary>
        /// 相关异常
        /// </summary>
        public Exception Exception { get; set; }
    }

    /// <summary>
    /// 模型熔断器
    /// </summary>
    public class ModelCircuitBreaker
    {
        private readonly CircuitBreakerConfig _config;
        private readonly object _stateLock = new object();
        private CircuitState _state = CircuitState.Closed;
        private DateTime _lastStateChange = DateTime.UtcNow;
        private int _consecutiveFailures = 0;
        private int _consecutiveSuccesses = 0;
        private int _halfOpenAttempts = 0;

        // 滑动窗口统计
        private readonly ConcurrentQueue<DateTime> _requestWindow = new();
        private readonly ConcurrentQueue<DateTime> _successWindow = new();
        private readonly ConcurrentQueue<DateTime> _failureWindow = new();

        /// <summary>
        /// 状态变更事件
        /// </summary>
        public event EventHandler<CircuitBreakerEventArgs> StateChanged;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="config">熔断器配置</param>
        public ModelCircuitBreaker(CircuitBreakerConfig config)
        {
            _config = config ?? throw new ArgumentNullException(nameof(config));
        }

        /// <summary>
        /// 当前状态
        /// </summary>
        public CircuitState State
        {
            get
            {
                lock (_stateLock)
                {
                    // 检查是否应该从开启状态切换到半开启状态
                    if (_state == CircuitState.Open &&
                        DateTime.UtcNow - _lastStateChange > TimeSpan.FromMilliseconds(_config.TimeoutMs))
                    {
                        ChangeState(CircuitState.HalfOpen, "Timeout elapsed, attempting recovery");
                    }
                    return _state;
                }
            }
        }

        /// <summary>
        /// 执行操作（带熔断保护）
        /// </summary>
        /// <param name="operation">要执行的操作</param>
        /// <returns>操作结果</returns>
        public async Task<T> ExecuteAsync<T>(Func<Task<T>> operation)
        {
            RecordRequest();

            if (State == CircuitState.Open)
            {
                throw new CircuitBreakerOpenException($"熔断器 '{_config.Name}' 已开启，拒绝请求");
            }

            try
            {
                var result = await operation();
                RecordSuccess();
                return result;
            }
            catch (Exception ex) when (_config.ExceptionFilter(ex))
            {
                RecordFailure(ex);
                throw;
            }
        }

        /// <summary>
        /// 执行操作（无返回值，带熔断保护）
        /// </summary>
        /// <param name="operation">要执行的操作</param>
        public async Task ExecuteAsync(Func<Task> operation)
        {
            RecordRequest();

            if (State == CircuitState.Open)
            {
                throw new CircuitBreakerOpenException($"熔断器 '{_config.Name}' 已开启，拒绝请求");
            }

            try
            {
                await operation();
                RecordSuccess();
            }
            catch (Exception ex) when (_config.ExceptionFilter(ex))
            {
                RecordFailure(ex);
                throw;
            }
        }

        /// <summary>
        /// 记录请求
        /// </summary>
        private void RecordRequest()
        {
            _requestWindow.Enqueue(DateTime.UtcNow);
            CleanupOldWindowEntries();
        }

        /// <summary>
        /// 记录成功
        /// </summary>
        private void RecordSuccess()
        {
            _successWindow.Enqueue(DateTime.UtcNow);
            CleanupOldWindowEntries();

            lock (_stateLock)
            {
                _consecutiveSuccesses++;
                _consecutiveFailures = 0;

                if (_state == CircuitState.HalfOpen)
                {
                    _halfOpenAttempts++;

                    // 半开启状态下达到成功阈值，关闭熔断器
                    if (_consecutiveSuccesses >= _config.SuccessThreshold)
                    {
                        ChangeState(CircuitState.Closed, "Recovery successful");
                        _halfOpenAttempts = 0;
                    }
                }
            }
        }

        /// <summary>
        /// 记录失败
        /// </summary>
        /// <param name="exception">异常</param>
        private void RecordFailure(Exception exception)
        {
            _failureWindow.Enqueue(DateTime.UtcNow);
            CleanupOldWindowEntries();

            lock (_stateLock)
            {
                _consecutiveFailures++;
                _consecutiveSuccesses = 0;

                switch (_state)
                {
                    case CircuitState.Closed:
                        // 关闭状态下达到失败阈值，开启熔断器
                        if (_consecutiveFailures >= _config.FailureThreshold)
                        {
                            ChangeState(CircuitState.Open, $"Failure threshold reached: {_consecutiveFailures}", exception);
                        }
                        break;

                    case CircuitState.HalfOpen:
                        // 半开启状态下失败，重新开启熔断器
                        ChangeState(CircuitState.Open, "Recovery attempt failed", exception);
                        _halfOpenAttempts = 0;
                        break;
                }
            }
        }

        /// <summary>
        /// 清理旧的窗口条目
        /// </summary>
        private void CleanupOldWindowEntries()
        {
            var cutoff = DateTime.UtcNow.AddMilliseconds(-_config.SlidingWindowMs);

            while (_requestWindow.TryPeek(out var timestamp) && timestamp < cutoff)
            {
                _requestWindow.TryDequeue(out _);
            }

            while (_successWindow.TryPeek(out var successTimestamp) && successTimestamp < cutoff)
            {
                _successWindow.TryDequeue(out _);
            }

            while (_failureWindow.TryPeek(out var failureTimestamp) && failureTimestamp < cutoff)
            {
                _failureWindow.TryDequeue(out _);
            }
        }

        /// <summary>
        /// 变更状态
        /// </summary>
        /// <param name="newState">新状态</param>
        /// <param name="reason">原因</param>
        /// <param name="exception">异常</param>
        private void ChangeState(CircuitState newState, string reason, Exception exception = null)
        {
            lock (_stateLock)
            {
                var oldState = _state;
                _state = newState;
                _lastStateChange = DateTime.UtcNow;

                if (newState == CircuitState.Closed)
                {
                    _consecutiveFailures = 0;
                    _consecutiveSuccesses = 0;
                    _halfOpenAttempts = 0;
                }
                else if (newState == CircuitState.Open)
                {
                    _halfOpenAttempts = 0;
                }

                OnStateChanged(new CircuitBreakerEventArgs
                {
                    CircuitBreakerName = _config.Name,
                    OldState = oldState,
                    NewState = newState,
                    Reason = reason,
                    Timestamp = DateTime.UtcNow,
                    Exception = exception
                });
            }
        }

        /// <summary>
        /// 触发状态变更事件
        /// </summary>
        /// <param name="args">事件参数</param>
        protected virtual void OnStateChanged(CircuitBreakerEventArgs args)
        {
            StateChanged?.Invoke(this, args);
        }

        /// <summary>
        /// 获取统计信息
        /// </summary>
        /// <returns>统计信息</returns>
        public CircuitBreakerStats GetStats()
        {
            CleanupOldWindowEntries();

            return new CircuitBreakerStats
            {
                TotalRequests = _requestWindow.Count,
                SuccessRequests = _successWindow.Count,
                FailedRequests = _failureWindow.Count,
                State = State,
                LastStateChange = _lastStateChange,
                ConsecutiveFailures = _consecutiveFailures,
                ConsecutiveSuccesses = _consecutiveSuccesses,
                HalfOpenAttemptCount = _halfOpenAttempts
            };
        }

        /// <summary>
        /// 重置熔断器
        /// </summary>
        public void Reset()
        {
            lock (_stateLock)
            {
                if (_state != CircuitState.Closed)
                {
                    ChangeState(CircuitState.Closed, "Manual reset");
                }

                _consecutiveFailures = 0;
                _consecutiveSuccesses = 0;
                _halfOpenAttempts = 0;

                _requestWindow.Clear();
                _successWindow.Clear();
                _failureWindow.Clear();
            }
        }

        /// <summary>
        /// 强制开启熔断器
        /// </summary>
        public void ForceOpen()
        {
            lock (_stateLock)
            {
                if (_state != CircuitState.Open)
                {
                    ChangeState(CircuitState.Open, "Force open");
                }
            }
        }
    }

    /// <summary>
    /// 熔断器开启异常
    /// </summary>
    public class CircuitBreakerOpenException : Exception
    {
        public CircuitBreakerOpenException(string message) : base(message) { }
    }

    /// <summary>
    /// 熔断器管理器
    /// </summary>
    public class CircuitBreakerManager
    {
        private readonly ConcurrentDictionary<string, ModelCircuitBreaker> _circuitBreakers = new();

        /// <summary>
        /// 获取或创建熔断器
        /// </summary>
        /// <param name="config">熔断器配置</param>
        /// <returns>熔断器实例</returns>
        public ModelCircuitBreaker GetOrCreateCircuitBreaker(CircuitBreakerConfig config)
        {
            return _circuitBreakers.GetOrAdd(config.Name, name => new ModelCircuitBreaker(config));
        }

        /// <summary>
        /// 获取所有熔断器的统计信息
        /// </summary>
        /// <returns>统计信息字典</returns>
        public Dictionary<string, CircuitBreakerStats> GetAllStats()
        {
            return _circuitBreakers.ToDictionary(
                kvp => kvp.Key,
                kvp => kvp.Value.GetStats()
            );
        }

        /// <summary>
        /// 重置所有熔断器
        /// </summary>
        public void ResetAll()
        {
            foreach (var circuitBreaker in _circuitBreakers.Values)
            {
                circuitBreaker.Reset();
            }
        }

        /// <summary>
        /// 移除熔断器
        /// </summary>
        /// <param name="name">熔断器名称</param>
        public void RemoveCircuitBreaker(string name)
        {
            _circuitBreakers.TryRemove(name, out _);
        }

        /// <summary>
        /// 获取熔断器
        /// </summary>
        /// <param name="name">熔断器名称</param>
        /// <returns>熔断器实例，如果不存在则返回null</returns>
        public ModelCircuitBreaker GetCircuitBreaker(string name)
        {
            return _circuitBreakers.TryGetValue(name, out var circuitBreaker) ? circuitBreaker : null;
        }
    }
}